package LeetDev.a3d;

import javax.microedition.khronos.opengles.GL10;

public class GeomNode extends Node {
	// Billboarding axis
	public static final int None=0;
	public static final int X=1;
	public static final int Y=2;
	public static final int Z=3;

	protected boolean m_billboard;
	protected int m_billboardAxis;
	protected Model m_model;
	protected Quat m_rotation;
	protected Vect m_scale;
	protected Matrix[] m_matrixlist;
	
	public GeomNode(final Vect pos,Model model)
	{
		m_model=model;
		m_model.addRef();
		m_billboardAxis=None;
		m_billboard=false;
		m_matrixlist=new Matrix[m_model.m_anims.length+1];
		for(int t=0;t<=m_model.m_anims.length;t++)
		{
			m_matrixlist[t]=new Matrix();
		}
		setPosition(pos);
		setScale(new Vect(1,1,1));
		setRotation(Quat.identity);
	}
	
	public void draw(GL10 gl)
	{
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		for(int t=0;t<m_model.m_hierarchy.length;t+=2)
		{
			int node=m_model.m_hierarchy[t];
			int object=m_model.m_hierarchy[t+1];
			switch(m_model.m_ImpObjs[object].GetType())
			{
				case 0:
				{
					((Mesh)(m_model.m_ImpObjs[object])).draw(m_matrixlist[node], gl);
				}
//				case 1:
//				{
//					((Joint*)(m_model->m_ImpObjs[object]))->use(*m_matrixlist[node]);
//				}
			}
		}
	}
	
	private static Matrix tmpAnimateMatrix=new Matrix();
	private static Matrix tmpAnimateMatrix2=new Matrix();
	private static Vect dir=new Vect();
	private static Vect right=new Vect();
	private static Vect up=new Vect();
	
	public void animate(GL10 gl, double ticks, double delta)
	{
		// scale
		for(int i=16;--i>=0;) {tmpAnimateMatrix2.m[i]=0;}
		tmpAnimateMatrix2.m[0]=m_scale.x;
		tmpAnimateMatrix2.m[5]=m_scale.y;
		tmpAnimateMatrix2.m[10]=m_scale.z;
		tmpAnimateMatrix2.m[15]=1;
		// rotation
		tmpAnimateMatrix.set(m_rotation);
		tmpAnimateMatrix2.special_mul(tmpAnimateMatrix,m_matrixlist[0]);
		Camera currentcamera=Camera.getCurrentCamera();
		if(m_billboard)
		{
			// billboarding
			if(m_billboardAxis==Z)
			{
				dir.x=0;dir.y=0;dir.z=1;
				currentcamera.getUp().cross(dir,right);
				right.normalize();
				dir.cross(right,up);
				up.normalize();
			}
			else if(m_billboardAxis==Y)
			{
				up.x=0;up.y=1;up.z=0;
				currentcamera.getPosition().sub(currentcamera.getLookAt(),dir);
				dir.normalize();
				up.cross(dir,right);
				right.normalize();
				right.cross(up,dir);
				dir.normalize();
			}
			else if(m_billboardAxis==X)
			{
				right.x=1;right.y=0;right.z=0;
				currentcamera.getPosition().sub(currentcamera.getLookAt(),dir);
				dir.normalize();
				dir.cross(right,up);
				up.normalize();
				right.cross(up,dir);
				dir.normalize();
			}
			else
			{
				currentcamera.getPosition().sub(currentcamera.getLookAt(),dir);
				dir.normalize();
				currentcamera.getUp().cross(dir,right);
				right.normalize();
				dir.cross(right,up);
				up.normalize();
			}
			tmpAnimateMatrix.m[3]=tmpAnimateMatrix.m[7]=tmpAnimateMatrix.m[11]=tmpAnimateMatrix.m[12]=tmpAnimateMatrix.m[13]=tmpAnimateMatrix.m[14]=0;
			tmpAnimateMatrix.m[15]=1;
			tmpAnimateMatrix.m[0]=right.x;tmpAnimateMatrix.m[1]=right.y;tmpAnimateMatrix.m[2]=right.z;
			tmpAnimateMatrix.m[4]=up.x;tmpAnimateMatrix.m[5]=up.y;tmpAnimateMatrix.m[6]=up.z;
			tmpAnimateMatrix.m[8]=dir.x;tmpAnimateMatrix.m[9]=dir.y;tmpAnimateMatrix.m[10]=dir.z;
			m_matrixlist[0].special_mul(tmpAnimateMatrix,tmpAnimateMatrix2);
			for(int i=16;--i>=0;) {m_matrixlist[0].m[i]=tmpAnimateMatrix2.m[i];}
		}
		//position
		m_matrixlist[0].m[12]=m_position.x;
		m_matrixlist[0].m[13]=m_position.y;
		m_matrixlist[0].m[14]=m_position.z;
		// animation
		
		for(int i=0; i<m_model.m_anims.length;++i)
		{
			m_model.m_anims[i].use(ticks,delta,m_matrixlist,i+1);
		}
	}

	public void setRotation(final Quat angle)
	{
		m_rotation=angle;
	}
	public void setRotation(final float w, final float x, final float y, final float z)
	{
		m_rotation.w=w;
		m_rotation.x=x;
		m_rotation.y=y;
		m_rotation.z=z;
	}
	public Quat getRotation()
	{
		return(m_rotation);
	}

	public void setScale(final Vect scale)
	{
		m_scale=scale;
	}
	public void setScale(final float x, final float y, final float z)
	{
		m_scale.x=x;
		m_scale.y=y;
		m_scale.z=z;
	}
	public Vect getScale()
	{
		return(m_scale);
	}

	public void setBillboarding(final boolean billboard)
	{
		m_billboard=billboard;
	}
	public boolean getBillboarding()
	{
		return(m_billboard);
	}
	public void setBillboardingAxis(final int axis)
	{
		m_billboardAxis=axis;
	}
	public int getBillboardingAxis()
	{
		return(m_billboardAxis);
	}

	// nodename=null selects all nodes in the model
	public void setAnimSpeed(double speed,final String nodename)
	{
		if(null==nodename)
		{
			for(int i=0; i<m_model.m_anims.length;++i)
			{
				m_model.m_anims[i].setSpeed(speed);
			}
		}
		else
		{
			for(int i=0; i<m_model.m_anims.length;++i)
			{
				if(m_model.m_anims[i].getName().compareTo(nodename)==0)
				{
					m_model.m_anims[i].setSpeed(speed);
					break;
				}
			}
		}
	}
	public double getAnimSpeed(final String nodename)
	{
		for(int i=0; i<m_model.m_anims.length;++i)
		{
			if(m_model.m_anims[i].getName().compareTo(nodename)==0)
			{
				return(m_model.m_anims[i].getSpeed());
			}
		}
		return(0);
	}
	// nodename=null selects all nodes in the model
	public void setAnimTime(double time,final String nodename)
	{
		if(null==nodename)
		{
			for(int i=0; i<m_model.m_anims.length;++i)
			{
				m_model.m_anims[i].setTime(time);
			}
		}
		else
		{
			for(int i=0; i<m_model.m_anims.length;++i)
			{
				if(m_model.m_anims[i].getName().compareTo(nodename)==0)
				{
					m_model.m_anims[i].setTime(time);
					break;
				}
			}
		}
	}
	public double getAnimTime(final String nodename)
	{
		for(int i=0; i<m_model.m_anims.length;++i)
		{
			if(m_model.m_anims[i].getName().compareTo(nodename)==0)
			{
				return(m_model.m_anims[i].getTime());
			}
		}
		return(0);
	}
	
}
